﻿using DBUtil.FastEntity.Annotations;
using DBUtil.MetaData;
using DotNetCommon.Extensions;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace DBUtil.FastEntity.Builders
{
    public static class ObjectExtentions
    {
        public static bool IsNumberic(this object obj)
        {
            var type = obj.GetType();
            var numbers = new List<Type>()
            {
                typeof(byte),
                typeof(sbyte),
                typeof(short),
                typeof(ushort),
                typeof(int),
                typeof(int?),
                typeof(long),
                typeof(ulong),
                typeof(float),
                typeof(float?),
                typeof(double),
                typeof(double?),
                typeof(decimal),
                typeof(decimal?)
            };
            return numbers.Contains(type);
        }
    }

    public class BuilderHelper<T> where T : class, new()
    {
        private Type EntityType = typeof(T);
        private List<string> stringBuilder = new List<string>();
        private List<IDataParameter> parameters = new List<IDataParameter>();
        private readonly SelectBuilder<T> selectBuilder;

        public BuilderHelper(SelectBuilder<T> selectBuilder)
        {
            this.selectBuilder = selectBuilder;
            #region string.IsNullOrEmpty
            //string.IsNullOrEmpty
            callDics.Add(typeof(string).GetMethod(nameof(string.IsNullOrEmpty)), _call_String_IsNullOrEmpty);
            //string.IsNullOrWhiteSpace
            callDics.Add(typeof(string).GetMethod(nameof(string.IsNullOrWhiteSpace)), _call_String_IsNullOrEmpty);
            //StringExtensions.IsNullOrEmpty
            callDics.Add(typeof(StringExtensions).GetMethod(nameof(StringExtensions.IsNullOrEmpty)), _call_String_IsNullOrEmpty);
            //StringExtensions.IsNullOrEmptyOrWhiteSpace
            callDics.Add(typeof(StringExtensions).GetMethod(nameof(StringExtensions.IsNullOrEmptyOrWhiteSpace)), _call_String_IsNullOrEmpty);

            //StringExtensions.IsNotNullOrEmpty
            callDics.Add(typeof(StringExtensions).GetMethod(nameof(StringExtensions.IsNotNullOrEmpty)), _call_String_IsNotNullOrEmpty);
            //StringExtensions.IsNotNullOrEmptyOrWhiteSpace
            callDics.Add(typeof(StringExtensions).GetMethod(nameof(StringExtensions.IsNotNullOrEmptyOrWhiteSpace)), _call_String_IsNotNullOrEmpty);
            #endregion
            #region string.Contains & string.StartsWith
            //string.Contains
            callDics.Add(typeof(string).GetMethod(nameof(string.Contains), new Type[] { typeof(string) }), _call_String_Contains);
            //string.StartsWith
            callDics.Add(typeof(string).GetMethod(nameof(string.StartsWith), new Type[] { typeof(string) }), _call_String_StartsWith);
            //string.EndsWith
            callDics.Add(typeof(string).GetMethod(nameof(string.EndsWith), new Type[] { typeof(string) }), _call_String_EndsWith);
            #endregion
            #region arr.Contains & List.Contains
            var ms = typeof(Enumerable).GetMethods().Where(i => i.Name == nameof(Enumerable.Contains)).ToList();
            ms.ForEach(m =>
            {
                var types = new List<Type>()
                {
                    typeof(int),
                    typeof(int?),
                    typeof(long),
                    typeof(long?),
                    typeof(string),
                    typeof(bool),
                    typeof(bool?),
                    typeof(short),
                    typeof(short?),
                    typeof(DateTime),
                    typeof(DateTime?),
                    typeof(double),
                    typeof(double?),
                    typeof(float),
                    typeof(float?),
                    typeof(decimal),
                    typeof(decimal?)
                };
                types.ForEach(t =>
                {
                    var _m = m.MakeGenericMethod(t);
                    callDics.Add(_m, _call_Enumerable_Contains);
                });
            });
            var type = typeof(List<>);
            var types = new List<Type>()
                {
                    typeof(int),
                    typeof(int?),
                    typeof(long),
                    typeof(long?),
                    typeof(string),
                    typeof(bool),
                    typeof(bool?),
                    typeof(short),
                    typeof(short?),
                    typeof(DateTime),
                    typeof(DateTime?),
                    typeof(double),
                    typeof(double?),
                    typeof(float),
                    typeof(float?),
                    typeof(decimal),
                    typeof(decimal?)
                };
            types.ForEach(t =>
            {
                var _m = type.MakeGenericType(t).GetMethod("Contains");
                callDics.Add(_m, _call_List_Contains);
            });
            #endregion

        }



        public string GetTableName()
        {
            return GetTableName(EntityType);
        }
        public string GetTableName(Type Type)
        {
            var mapTable = Type.GetAttributeToPropertyMapping<MapTableAttribute>(true);
            if (EntityType.TryGetAttributes<MapTableAttribute>(out MapTableAttribute[] map, true))
            {
                var t = map.ToList().FirstOrDefault();
                return t.Name;
            }
            return EntityType.Name;
        }

        public string GetColName(MemberInfo memberInfo)
        {
            var colAttr = memberInfo.GetCustomAttribute<MapColumnAttribute>();
            if (colAttr != null && !colAttr.Name.IsNullOrEmptyOrWhiteSpace()) return colAttr.Name;
            return memberInfo.Name;
        }


        public List<(string name, KeyStrategy keyStrategy, Type type)> GetKeys()
        {
            var res = new List<(string name, KeyStrategy keyStrategy, Type type)>();
            var keys = EntityType.GetAttributeToPropertyMapping<MapKeyAttribute>(true);
            if (keys.Count == 0) return res;
            keys.ForEach(p =>
            {
                var name = p.Key.Name;
                if (string.IsNullOrWhiteSpace(name)) name = p.Value.Name;
                var keyStrategy = p.Key.KeyStrategy;
                var type = p.Value.PropertyType;
                res.Add((name, keyStrategy, type));
            });
            return res;
        }       

        /// <summary>
        /// lambda表达式解析入口
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public (string sql, IDataParameter[]) ParseLamda(LambdaExpression exp)
        {
            if (exp.NodeType != ExpressionType.Lambda) throw new Exception($"不正确的lambda表达式:{exp}");
            if (exp.ReturnType != typeof(bool)) throw new Exception($"lambda表达式的返回值必须是bool类型:{exp}");
            stringBuilder.Clear();
            parameters.Clear();
            var lambda = exp as LambdaExpression;
            var body = lambda.Body;
            stringBuilder.Add("(");
            #region 保证完整性
            //转换的不处理
            var _body = body;
            while (_body.NodeType == ExpressionType.Convert)
            {
                _body = (_body as UnaryExpression).Operand;
            }
            if (_body.NodeType == ExpressionType.MemberAccess)
            {
                //检查确保完整性
                dispatch(_body);
                var last = stringBuilder.Last();
                if (last == "1")
                {
                    stringBuilder.Add("=");
                    stringBuilder.Add("1");
                }
                else if (last == "0")
                {
                    stringBuilder.Add(">");
                    stringBuilder.Add("0");
                }
                else
                {
                    //字段
                    stringBuilder.Add("=");
                    stringBuilder.Add("1");
                }
            }
            else if (_body.NodeType == ExpressionType.Constant)
            {
                var res = (_body as ConstantExpression).Value.To<bool>();
                if (res)
                {
                    stringBuilder.Add("1=1");
                }
                else
                {
                    stringBuilder.Add("1<>1");
                }
            }
            else
            {
                dispatch(body);
            }
            #endregion
            stringBuilder.Add(")");
            return (string.Join(" ", stringBuilder), parameters.ToArray());
        }

        public void dispatch(Expression exp, bool isNot = false)
        {
            switch (exp.NodeType)
            {
                case ExpressionType.Equal://: =
                    {
                        VisitEqual(exp, isNot);
                        break;
                    }
                case ExpressionType.NotEqual://: <>
                    {
                        VisitNotEqual(exp, isNot);
                        break;
                    }
                case ExpressionType.LessThan://: <
                    {
                        VisitLessThan(exp, isNot);
                        break;
                    }
                case ExpressionType.LessThanOrEqual://: <=
                    {
                        VisitLessThanOrEqual(exp, isNot);
                        break;
                    }
                case ExpressionType.GreaterThan://: >
                    {
                        VisitGreaterThan(exp, isNot);
                        break;
                    }
                case ExpressionType.GreaterThanOrEqual://: >=
                    {
                        VisitGreaterThanOrEqual(exp, isNot);
                        break;
                    }
                case ExpressionType.AndAlso://: and
                    {
                        VisitAndAlso(exp, isNot);
                        break;
                    }
                case ExpressionType.OrElse://: or
                    {
                        VisitOrElse(exp, isNot);
                        break;
                    }
                case ExpressionType.Not://: !
                    {
                        VisitNot(exp, isNot);
                        break;
                    }
                case ExpressionType.Constant:
                    {
                        VisitConstant(exp);
                        break;
                    }
                case ExpressionType.MemberAccess:
                    {
                        VisitMemberAccess(exp);
                        break;
                    }
                case ExpressionType.Convert:
                    {
                        VisitConvert(exp);
                        break;
                    }
                case ExpressionType.Call:// 方法调用,TODO: 检查调用的方法必须返回bool类型
                    {
                        VisitCall(exp, isNot);
                        break;
                    }
                case ExpressionType.Conditional://三元运算符
                    {
                        VisitConditional(exp, isNot);
                        break;
                    }
                default:
                    {
                        throw new Exception($"无法解析的表达式类型:{exp}");
                    }
            }
        }

        private void VisitConditional(Expression exp, bool isNot)
        {
            //三元运算符,左侧不允许出现参数
            var condition = exp as ConditionalExpression;
            if (condition.Test.NodeType == ExpressionType.MemberAccess)
            {
                var flag = _VisitMemberAccess(condition.Test).To<bool>();
                if (flag)
                {
                    dispatch(condition.IfTrue);
                }
                else
                {
                    dispatch(condition.IfFalse);
                }
            }
            else
            {

            }
        }

        private void _VisitAndOr(Expression exp, string code, bool isNot)
        {
            var binary = exp as BinaryExpression;
            stringBuilder.Add("(");
            #region 保证左侧完整
            //转换的不处理
            var _left = binary.Left;
            while (_left.NodeType == ExpressionType.Convert)
            {
                _left = (_left as UnaryExpression).Operand;
            }
            if (_left.NodeType == ExpressionType.MemberAccess)
            {
                //检查确保完整性
                dispatch(binary.Left, isNot);
                var last = stringBuilder.Last();
                if (last == "1")
                {
                    stringBuilder.Add("=");
                    stringBuilder.Add(isNot ? "0" : "1");
                }
                else if (last == "0")
                {
                    stringBuilder.Add(">");
                    stringBuilder.Add(isNot ? "1" : "0");
                }
                else
                {
                    //字段
                    stringBuilder.Add("=");
                    stringBuilder.Add(isNot ? "0" : "1");
                }
            }
            else if (_left.NodeType == ExpressionType.Constant)
            {
                var res = (_left as ConstantExpression).Value.To<bool>();
                if (res)
                {
                    stringBuilder.Add(isNot ? "1<>1" : "1=1");
                }
                else
                {
                    stringBuilder.Add(isNot ? "1=1" : "1<>1");
                }
            }
            else
            {
                dispatch(binary.Left, isNot);
            }
            #endregion
            stringBuilder.Add(")");
            stringBuilder.Add(code);
            stringBuilder.Add("(");
            #region 保证右侧完整
            //转换的不处理
            var _right = binary.Right;
            while (_right.NodeType == ExpressionType.Convert)
            {
                _right = (_right as UnaryExpression).Operand;
            }
            if (_right.NodeType == ExpressionType.MemberAccess)
            {
                //检查确保完整性
                dispatch(binary.Right, isNot);
                var last = stringBuilder.Last();
                if (last == "1")
                {
                    stringBuilder.Add("=");
                    stringBuilder.Add(isNot ? "0" : "1");
                }
                else if (last == "0")
                {
                    stringBuilder.Add(">");
                    stringBuilder.Add(isNot ? "1" : "0");
                }
                else
                {
                    //字段
                    stringBuilder.Add("=");
                    stringBuilder.Add(isNot ? "0" : "1");
                }
            }
            else if (_right.NodeType == ExpressionType.Constant)
            {
                var res = (_right as ConstantExpression).Value.To<bool>();
                if (res)
                {
                    stringBuilder.Add(isNot ? "1<>1" : "1=1");
                }
                else
                {
                    stringBuilder.Add(isNot ? "1=1" : "1<>1");
                }
            }
            else
            {
                dispatch(binary.Right, isNot);
            }
            #endregion            
            stringBuilder.Add(")");
        }

        public void VisitAndAlso(Expression exp, bool isNot)
        {
            _VisitAndOr(exp, isNot ? "or" : "and", isNot);
        }

        public void VisitOrElse(Expression exp, bool isNot)
        {
            _VisitAndOr(exp, isNot ? "and" : "or", isNot);
        }

        public void VisitNot(Expression exp, bool isNot)
        {
            var unary = exp as UnaryExpression;
            #region 保证左侧完整
            //转换的不处理
            var _op = unary.Operand;
            while (_op.NodeType == ExpressionType.Convert)
            {
                _op = (_op as UnaryExpression).Operand;
            }
            if (_op.NodeType == ExpressionType.MemberAccess)
            {
                //检查确保完整性
                isNot = !isNot;
                dispatch(_op, isNot);
                var last = stringBuilder.Last();
                var count = stringBuilder.Count;
                if (count >= 2 && (stringBuilder[count - 2] == "=" || stringBuilder[count - 2] == "<>"))
                {
                    //返回值不用于逻辑运算,如:person.Select(p=>true==!p.Active)
                    if (last == "1")
                    {
                        //返回的是变量或常量结果: person.Select(p => !true);
                        stringBuilder.RemoveAt(count - 1);
                        stringBuilder.Add(isNot ? "0" : "1");
                    }
                    else if (last == "0")
                    {
                        //返回的是变量或常量结果: person.Select(p => !false);
                        stringBuilder.RemoveAt(count - 1);
                        stringBuilder.Add(isNot ? "1" : "0");
                    }
                    else
                    {
                        //返回的是字段,如: [Active]
                        var t = stringBuilder[count - 2];
                        if (t == "=")
                        {
                            stringBuilder[count - 2] = (isNot ? "<>" : "=");
                        }
                        else if (t == "<>")
                        {
                            stringBuilder[count - 2] = (isNot ? "=" : "<>");
                        }
                    }
                }
                else
                {
                    //返回值直接用于逻辑运算:person.Select(p=>true&&(!p.Active))
                    if (last == "1")
                    {
                        //返回的是变量或常量结果: person.Select(p=>!true);
                        stringBuilder.Add("=");
                        stringBuilder.Add(isNot ? "0" : "1");
                    }
                    else if (last == "0")
                    {
                        //返回的是变量或常量结果: person.Select(p => !false);
                        stringBuilder.Add(">");
                        stringBuilder.Add(isNot ? "1" : "0");
                    }
                    else
                    {
                        //返回的是字段,如: [Active]
                        stringBuilder.Add("=");
                        stringBuilder.Add(isNot ? "0" : "1");
                    }
                }
            }
            else
            {
                dispatch(unary.Operand, isNot ? false : true);
            }
            #endregion
        }

        #region = <> > >= < <=
        private void _Visite(Expression exp, string code)
        {
            var binary = exp as BinaryExpression;
            dispatch(binary.Left);
            stringBuilder.Add(code);
            dispatch(binary.Right);
        }
        public void VisitEqual(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? "<>" : "=");
        }
        public void VisitNotEqual(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? "=" : "<>");
        }
        public void VisitGreaterThan(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? "<=" : ">");
        }
        public void VisitLessThan(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? ">=" : "<");
        }
        public void VisitLessThanOrEqual(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? ">" : "<=");
        }
        public void VisitGreaterThanOrEqual(Expression exp, bool isNot)
        {
            _Visite(exp, isNot ? "<" : ">=");
        }
        #endregion

        public void VisitConvert(Expression exp)
        {
            var unary = exp as UnaryExpression;
            //不处理转换
            dispatch(unary.Operand);
        }

        private Dictionary<MethodInfo, Action<MethodCallExpression, bool>> callDics = new Dictionary<MethodInfo, Action<MethodCallExpression, bool>>();
        public void VisitCall(Expression exp, bool isNot)
        {
            var call = exp as MethodCallExpression;
            var m = call.Method;
            if (!callDics.ContainsKey(m)) throw new Exception($"无法解析的方法调用:{m.DeclaringType.FullName}:{m}");
            var act = callDics[m];
            act(call, isNot);
        }
        private void _call_String_IsNullOrEmpty(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            if (isNot)
            {
                stringBuilder.Add($"{val} is not null and {val} <> ''");
            }
            else
            {
                stringBuilder.Add($"{val} is null or {val} = ''");
            }
        }

        private void _call_String_IsNotNullOrEmpty(MethodCallExpression exp, bool isNot)
        {
            _call_String_IsNullOrEmpty(exp, !isNot);
        }

        private void _call_String_Contains(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            var obj = _VisitMemberAccess(exp.Object);
            if (isNot)
            {
                stringBuilder.Add($"{obj} not like '%{val ?? "".Replace("'", "''")}%'");
            }
            else
            {
                stringBuilder.Add($"{obj} like '%{val ?? "".Replace("'", "''")}%'");
            }
        }

        private void _call_String_StartsWith(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            var obj = _VisitMemberAccess(exp.Object);
            if (isNot)
            {
                stringBuilder.Add($"{obj} not like '{(val ?? "").ToString().Replace("'", "''")}%'");
            }
            else
            {
                stringBuilder.Add($"{obj} like '{(val ?? "").ToString().Replace("'", "''")}%'");
            }
        }

        private void _call_String_EndsWith(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            var obj = _VisitMemberAccess(exp.Object);
            if (isNot)
            {
                stringBuilder.Add($"{obj} not like '%{(val ?? "").ToString().Replace("'", "''")}'");
            }
            else
            {
                stringBuilder.Add($"{obj} like '%{(val ?? "").ToString().Replace("'", "''")}'");
            }
        }

        private string ObjectJoin(IEnumerable arr)
        {
            var res = new List<string>();
            foreach (var i in arr)
            {
                if (i == null) res.Add("null");
                else if (i.IsNumberic()) res.Add(i.ToString());
                else if (i is DateTime d) res.Add(selectBuilder.db.Expression_DateTime.GetStringInSql(d));
                else if (i is DateTime?) res.Add(selectBuilder.db.Expression_DateTime.GetStringInSql(((DateTime?)i).Value));
                else if (i is string) res.Add("'" + i.ToString().Replace("'", "''") + "'");
            }
            return string.Join(",", res);
        }
        private List<object> ToArray(object arr)
        {
            var res = new List<object>();
            if (arr is Array)
            {
                var t = (Array)arr;
                foreach (var item in t)
                {
                    res.Add(item);
                }
            }
            return res;
        }


        private void _call_Enumerable_Contains(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            var obj = _VisitMemberAccess(exp.Arguments[1]);
            var content = "";
            //数组判断
            #region 数组
            if (val is Array)
            {
                var arr = ToArray(val);
                content = ObjectJoin(arr);
            }
            else if (val is List<object> arr)
            {
                content = ObjectJoin(arr);
            }
            #endregion
            if (isNot)
            {
                stringBuilder.Add($"{obj} not in ({content})");
            }
            else
            {
                stringBuilder.Add($"{obj} in ({content})");
            }
        }
        private void _call_List_Contains(MethodCallExpression exp, bool isNot)
        {
            var val = _VisitMemberAccess(exp.Arguments.FirstOrDefault());
            var obj = _VisitMemberAccess(exp.Object);
            var content = "";
            //数组判断
            #region 集合
            if (obj.GetType().FullName.StartsWith("System.Collections.Generic.List`1"))
            {
                content = ObjectJoin((IEnumerable)obj);
            }
            #endregion
            if (isNot)
            {
                stringBuilder.Add($"{val} not in ({content})");
            }
            else
            {
                stringBuilder.Add($"{val} in ({content})");
            }
        }




        public void VisitConstant(Expression exp)
        {
            var constant = exp as ConstantExpression;
            if (constant.Value == null)
            {
                if (stringBuilder.Last() == "=")
                {
                    stringBuilder[stringBuilder.Count - 1] = "is";
                }
                else if (stringBuilder.Last() == "<>")
                {
                    stringBuilder[stringBuilder.Count - 1] = "is not";
                }
                else
                {
                    //其他的也当做不相等处理
                    stringBuilder[stringBuilder.Count - 1] = "is not";
                }
                stringBuilder.Add("null");
            }
            else
            {
                var fullname = constant.Type.FullName;
                switch (fullname)
                {
                    //整形
                    case "System.SByte": // sbyte
                    case "System.Int16": // short
                    case "System.Int32": // int
                    case "System.Int64": // long
                    case "System.Byte": // byte
                    case "System.UInt16": // ushort
                    case "System.UInt32": // uint
                    case "System.UInt64": //ulong

                    //浮点
                    case "System.Single": //float
                    case "System.Double": //double
                    case "System.Decimal": //decimal
                        {
                            stringBuilder.Add(constant.Value.ToString());
                            break;
                        }
                    case "System.Boolean":
                        {
                            var val = constant.Value.To<bool>();
                            if (val) stringBuilder.Add("1");
                            else stringBuilder.Add("0");
                            break;
                        }
                    case "System.String":
                        {
                            stringBuilder.Add($"'{constant.Value.ToString().Replace("'", "''")}'");
                            break;
                        }
                }
            }
        }

        public void VisitMemberAccess(Expression exp)
        {
            var member = exp as MemberExpression;
            var mem = member.Member;
            object final = null;
            if (member.Expression != null && member.Expression.NodeType == ExpressionType.Parameter)
            {
                //静态属性的Expression为null
                var colname = GetColName(mem);
                stringBuilder.Add($"[{colname}]");
                return;
            }
            //先获取到member.Expression中的值(递归获取)
            object val = _VisitMemberAccess(member.Expression);
            //再获取到对应的实际值
            if (member.Member.MemberType == MemberTypes.Property)
            {
                final = (member.Member as PropertyInfo).GetValue(val);
            }
            else if (member.Member.MemberType == MemberTypes.Field)
            {
                final = member.Member.DeclaringType.GetField(member.Member.Name).GetValue(val);
            }
            if (final == null)
            {
                if (stringBuilder.Last() == "=")
                {
                    stringBuilder[stringBuilder.Count - 1] = "is";
                }
                else if (stringBuilder.Last() == "<>")
                {
                    stringBuilder[stringBuilder.Count - 1] = "is not";
                }
                stringBuilder.Add("null");
            }
            else if (final is string)
            {
                stringBuilder.Add($"'{final.ToString().Replace("'", "''")}'");
            }
            else if (final is DateTime d)
            {
                stringBuilder.Add(selectBuilder.db.Expression_DateTime.GetStringInSql(d));
            }
            else if (final is bool b)
            {
                stringBuilder.Add($"{(b ? "1" : "0")}");
            }
            else
            {
                stringBuilder.Add($"{final}");
            }
        }

        public object _VisitMemberAccess(Expression exp)
        {
            if (exp == null) return null;
            if (exp.NodeType == ExpressionType.Constant) return (exp as ConstantExpression).Value;
            //转换的不处理
            while (exp.NodeType == ExpressionType.Convert)
            {
                exp = (exp as UnaryExpression).Operand;
            }
            if (exp.NodeType == ExpressionType.Constant) return (exp as ConstantExpression).Value;
            //初始化数组
            if (exp.NodeType == ExpressionType.NewArrayInit)
            {
                var arrInit = (exp as NewArrayExpression).Expressions;
                var arr = arrInit.ToList();
                var res = arr.Select(i => _VisitMemberAccess(i)).ToList();
                return res;
            }
            //初始化集合
            if (exp.NodeType == ExpressionType.ListInit)
            {
                //return (exp as NewArrayExpression).Expressions;
                var listInit = (exp as ListInitExpression);
                var res = listInit.Initializers.Select(i => _VisitMemberAccess(i.Arguments.FirstOrDefault())).ToList();
                return res;
            }
            var member = exp as MemberExpression;
            var mem = member.Member;
            if (member.Expression != null && member.Expression.NodeType == ExpressionType.Parameter)
            {
                //静态属性的Expression为null
                var colname = GetColName(mem);
                return $"[{colname}]";
            }
            if (exp.NodeType == ExpressionType.MemberAccess)
            {
                object val = null;
                if (member.Member.MemberType == MemberTypes.Property)
                {
                    val = (member.Member as PropertyInfo).GetValue(_VisitMemberAccess(member.Expression));
                }
                else if (member.Member.MemberType == MemberTypes.Field)
                {
                    val = member.Member.DeclaringType.GetField(member.Member.Name).GetValue(_VisitMemberAccess(member.Expression));
                }
                return val;
            }
            return null;
        }
    }
}
